﻿// g_wsaEventSelect_Client.cpp : Defines the entry point for the console application.
//
#include <vector>
#include <Winsock2.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#include <iostream>
#include <algorithm>

#pragma comment(lib,"Ws2_32.lib")
using namespace std;

SOCKET g_socketServer = INVALID_SOCKET;
WSAEVENT g_wsaEvent = WSA_INVALID_EVENT;

//注册点位时要发送的结构体
typedef struct info{
	int length;
	int dots[1000];		
}info;

// 初始化socket
void InitSock()
{
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 2, 2 );
	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		return;
	}

	/* Confirm that the WinSock DLL supports 2.2.        */
	/* Note that if the DLL supports versions greater    */
	/* than 2.2 in addition to 2.2, it will still return */
	/* 2.2 in wVersion since that is the version we      */
	/* requested.                                        */
	if ( LOBYTE( wsaData.wVersion ) != 2 ||
			HIBYTE( wsaData.wVersion ) != 2 ) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		WSACleanup( );
		return; 
	}
}

void UnInitSock()
{
	if (g_wsaEvent != WSA_INVALID_EVENT)
	{
		WSACloseEvent(g_wsaEvent);
	}
	if (g_socketServer != INVALID_SOCKET)
	{
		closesocket(g_socketServer);
	}
	WSACleanup();
}

struct ST_THREAD_PARAM
{
	SOCKET socket;
	WSAEVENT wsaEvent;
};


int main(int argc, char* argv[])
{
	int number;
	InitSock();
	g_socketServer=socket(AF_INET,SOCK_STREAM,0);
	if (g_socketServer == INVALID_SOCKET)
	{
		UnInitSock();
		return -1;
	}
	sockaddr_in sin;
	sin.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	sin.sin_family=AF_INET;
	sin.sin_port=htons(8089);	
	if (connect(g_socketServer,(sockaddr*)&sin,sizeof(sockaddr)) == SOCKET_ERROR)
	{
		cout << ("connect failed!") << endl << "出错代码：" << WSAGetLastError() << endl << "出错文件：" << __FILE__ << endl << "出错行数：" << __LINE__ << endl;
		UnInitSock();
		return -1;
	}
	g_wsaEvent=::WSACreateEvent();
	::WSAEventSelect(g_socketServer,g_wsaEvent,FD_READ|FD_WRITE|FD_CLOSE);

	while(true)
	{
		int nRet=::WSAWaitForMultipleEvents(1,&g_wsaEvent,FALSE,10000,FALSE);
		if(nRet==WAIT_FAILED) // 失败
		{
			printf("failed wait for single object/n");
			break;
		}
		else if(nRet==WSA_WAIT_TIMEOUT) // 超时
		{
			//printf(" WSA_WAIT_TIMEOUT ... \n");
			continue;
		}
		else // 成功 -- 网络事件发生
		{
			WSANETWORKEVENTS wsaNetEvent;
			::WSAEnumNetworkEvents(g_socketServer,g_wsaEvent,&wsaNetEvent);
			if(wsaNetEvent.lNetworkEvents&FD_READ)
			{
				char buffer[100];
				int nRet = recv(g_socketServer,buffer,100,0);
				if (nRet>0)
				{
					buffer[nRet] = '\0';
					printf("收到数据 %s\n",buffer);
				}
				else
				{
					UnInitSock();
					return -1;
				}
				
			}
			else if(wsaNetEvent.lNetworkEvents&FD_WRITE)
			{
				info struct_dots;
				
				//辅助数组存1000个点位值
				int assis_array[1000],assis=1000,sub,tmp;
				for(int i=0;i<1000;i++) assis_array[i]=i+1;
				
				//生产30个随机点位并发送注册
				srand((unsigned)time(NULL));
				for (int i=0;i<30;i++)
				{
					sub=rand()%assis;
					tmp=assis_array[sub];
					assis_array[sub]=assis_array[assis-1];
					assis--;
					struct_dots.dots[i]=tmp;
				}
				//进行一个点位大小排序
				sort(struct_dots.dots,(struct_dots.dots)+30,less<int>());
				
				//struct_dots.length=number;
				struct_dots.length=30;
				cout<< "number of dots: "<<struct_dots.length<<endl;
				cout << "length of struct_dots: "<< sizeof(struct_dots)<<endl;
				for (int i=0 ; i<struct_dots.length;i++)
				{
					cout<< struct_dots.dots[i]<<endl;
				}
				
				char msg[10240];
				memcpy(msg, &struct_dots, sizeof(struct_dots));
				send(g_socketServer,msg,sizeof(struct_dots),0);
				
			}
			if(wsaNetEvent.lNetworkEvents&FD_CLOSE)
			{
				printf("FD_CLOSE event occurs...\n");
				int nErrorCode = WSAGetLastError();
				printf("Error code is %d\n",nErrorCode);
				if (nErrorCode == WSAECONNRESET)
				{
					printf("WSAECONNRESET error.\n");
				}
				else if (nErrorCode == WSAENETDOWN)
				{
					printf("WSAENETDOWN error.\n");
				}
				else if (nErrorCode == WSAENETRESET)
				{
					printf("WSAENETRESET error.\n");
				}
				UnInitSock();
				return -1;
			}
		}
	}
	return 0;
}
